﻿/*
 * $Id$
 */ 
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.IO;

namespace discoverter
{
    public static class Discoverter
    {
        private static readonly string aspxHeader = "<%@ Page Language=\"C#\" Inherits=\"System.Web.UI.Page\"    %>" + Environment.NewLine +
                                    "<%@ Assembly Name=\"{0}\" %>" + Environment.NewLine +
                                    "<%@ Import Namespace=\"Microsoft.SharePoint.Utilities\" %>" + Environment.NewLine +
                                    "<%@ Import Namespace=\"Microsoft.SharePoint\" %>" + Environment.NewLine +
                                    "<% Response.ContentType = \"text/xml\"; %>" + Environment.NewLine;

        private static readonly string Assembly12 =
            "Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";
        private static readonly string Assembly14 =
            "Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c";

        /// <summary>
        /// Read a .wsdl File and convert it into a WSSv3/MOSS2007 compatible wsdl.aspx file
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private static string ConvertWsdlFile(string filename, bool sharepoint2010)
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.Load(filename);
            XmlNamespaceManager xm = new XmlNamespaceManager(xdoc.NameTable);
            xm.AddNamespace("wsdl", "http://schemas.xmlsoap.org/wsdl/");

            string xpathService = @"wsdl:definitions/wsdl:service";
            string xpathPorts = @"wsdl:port";
            XmlNodeList serviceNodes = xdoc.SelectNodes(xpathService, xm);
            foreach (XmlNode serviceNode in serviceNodes)
            {
                XmlNodeList portNodes = serviceNode.SelectNodes(xpathPorts, xm);
                foreach (XmlNode portNode in portNodes)
                {
                    foreach (XmlNode addressNode in portNode.ChildNodes)
                    {
                        if (addressNode.Attributes["location"] != null)
                        {
                            addressNode.Attributes["location"].Value = @"###REPLACE###";
                        }
                    }
                }
            }

            var aspxHeaderConverted = string.Format(aspxHeader, sharepoint2010 ? Assembly14 : Assembly12);

            string convertedXml = string.Concat(aspxHeaderConverted, xdoc.DocumentElement.OuterXml.Replace("\"###REPLACE###\"", @"<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>"));
            return convertedXml;
        }

        private static string ConvertDiscoFile(string filename, bool sharepoint2010)
        {
            XmlDocument xdoc = new XmlDocument();
            xdoc.Load(filename);
            XmlNamespaceManager xm = new XmlNamespaceManager(xdoc.NameTable);
            xm.AddNamespace("disco", "http://schemas.xmlsoap.org/disco/");
            XmlNodeList discoNodes = xdoc.SelectNodes("disco:discovery/*", xm);
            foreach (XmlNode discoNode in discoNodes)
            {
                if (discoNode.Name == "contractRef")
                {
                    if(discoNode.Attributes["ref"] != null){
                        discoNode.Attributes["ref"].Value = @"###REPLACE-CONTRACTREF###";
                    }

                    if (discoNode.Attributes["docRef"] != null)
                    {
                        discoNode.Attributes["docRef"].Value = @"###REPLACE-ADDRESS###";
                    }
                }
                else if (discoNode.Name == "soap")
                {
                    if (discoNode.Attributes["address"] != null)
                    {
                        discoNode.Attributes["address"].Value = @"###REPLACE-ADDRESS###";
                    }
                }
            }

            string convertedXml = xdoc.DocumentElement.OuterXml.Replace("\"###REPLACE-CONTRACTREF###\"", "<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + \"?wsdl\"),Response.Output); %>");
            convertedXml = convertedXml.Replace("\"###REPLACE-ADDRESS###\"", "<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>");

            var aspxHeaderConverted = string.Format(aspxHeader, sharepoint2010 ? Assembly14 : Assembly12);
            return string.Concat(aspxHeaderConverted, convertedXml);
        }

        public static void ConvertServiceFiles(string discoFilename, string wsdlFilename, string outputDirectory, bool sharepoint2010)
        {
            if (!Directory.Exists(outputDirectory))
            {
                throw new DirectoryNotFoundException("Output Directory does not exist!");
            }
            if (!File.Exists(discoFilename))
            {
                throw new FileNotFoundException(".disco file does not exist!");
            }
            if (!File.Exists(wsdlFilename))
            {
                throw new FileNotFoundException(".wsdl file does not exist!");
            }
            string convertedDisco, convertedWsdl;
            string outputDiscoFilename = Path.Combine(outputDirectory, string.Format("{0}disco.aspx", Path.GetFileNameWithoutExtension(discoFilename)));
            string outputWsdlFilename = Path.Combine(outputDirectory, string.Format("{0}wsdl.aspx", Path.GetFileNameWithoutExtension(wsdlFilename)));

            convertedDisco = ConvertDiscoFile(discoFilename, sharepoint2010);
            convertedWsdl = ConvertWsdlFile(wsdlFilename, sharepoint2010);

            StreamWriter sw = File.CreateText(outputDiscoFilename);
            sw.Write(convertedDisco);
            sw.Flush();
            sw.Close();

            sw = File.CreateText(outputWsdlFilename);
            sw.Write(convertedWsdl);
            sw.Flush();
            sw.Close();
        }


    }
}
